package com.gitee.hengboy.mybatis.enhance.key.generator;

import com.gitee.hengboy.mybatis.enhance.common.ConfigConstants;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.executor.ExecutorException;
import org.apache.ibatis.executor.keygen.KeyGenerator;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.reflection.MetaObject;

import java.sql.Statement;
import java.util.*;

/**
 * The {@link KeyGenerator} abstract support
 *
 * @author 恒宇少年
 */
public abstract class AbstractKeyGenerator implements KeyGenerator {
    protected abstract void batchProcessBefore(MappedStatement ms, Collection<Object> statementParameters);

    @Override
    public void processBefore(Executor executor, MappedStatement ms, Statement statement, Object parameter) {
        this.batchProcessBefore(ms, getParameters(parameter));
    }

    @Override
    public void processAfter(Executor executor, MappedStatement mappedStatement, Statement statement, Object o) {
        // nothing to do
    }

    protected void setPkFieldValue(MetaObject metaParam, String property, Object value) {
        if (metaParam.hasSetter(property)) {
            metaParam.setValue(property, value);
        } else {
            throw new ExecutorException("No setter found for the keyProperty '" + property + "' in " + metaParam.getOriginalObject().getClass().getName() + ".");
        }
    }

    /**
     * 沿用Jdbc3KeyGenerator内解析参数的方法实现
     *
     * @param parameter 请求对象
     * @return 参数集合
     * @see org.apache.ibatis.executor.keygen.Jdbc3KeyGenerator
     */
    protected Collection<Object> getParameters(Object parameter) {
        Collection<Object> parameters = null;
        if (parameter instanceof Collection) {
            parameters = (Collection) parameter;
        } else if (parameter instanceof Map) {
            Map parameterMap = (Map) parameter;
            // 如果参数map内存在,key=collection的@Param时
            if (parameterMap.containsKey(ConfigConstants.COLLECTION_PARAMETER_NAME)) {
                Object collection = parameterMap.get(ConfigConstants.COLLECTION_PARAMETER_NAME);
                if (collection instanceof Collection) {
                    parameters = (Collection) collection;
                } else if (collection instanceof Object[]) {
                    parameters = Arrays.asList((Object[]) collection);
                }
            }
            // 如果参数map内存在,key=array的@Param时
            else if (parameterMap.containsKey(ConfigConstants.LIST_PARAMETER_NAME)) {
                parameters = (List) parameterMap.get(ConfigConstants.LIST_PARAMETER_NAME);
            }
            // 如果参数map内存在,key=array的@Param时
            else if (parameterMap.containsKey(ConfigConstants.ARRAY_PARAMETER_NAME)) {
                parameters = Arrays.asList((Object[]) parameterMap.get(ConfigConstants.ARRAY_PARAMETER_NAME));
            }
            // 如果参数map内存在,key=bean的@Param时
            else if (parameterMap.containsKey(ConfigConstants.BEAN_PARAMETER_NAME)) {
                parameters = Arrays.asList((Object) parameterMap.get(ConfigConstants.BEAN_PARAMETER_NAME));
            }
        }

        if (parameters == null) {
            parameters = new ArrayList();
            parameters.add(parameter);
        }

        return parameters;
    }
}
